//package com.xxl.job.executor.service.jobhandler.backupver;
//
//import com.xxl.job.core.context.XxlJobHelper;
//import com.xxl.job.core.util.GsonTool;
//import com.xxl.job.executor.model.Constants;
//import com.xxl.job.executor.model.to.FtpParam;
//import com.xxl.job.executor.utils.FileFilterUtil;
//import io.micrometer.common.util.StringUtils;
//import org.apache.commons.net.ftp.FTPClient;
//import org.apache.commons.net.ftp.FTPFile;
//import org.apache.commons.net.ftp.FTPReply;
//import org.springframework.stereotype.Component;
//
//import java.io.*;
//import java.io.RandomAccessFile;
//import java.nio.charset.StandardCharsets;
//import java.text.ParseException;
//import java.text.SimpleDateFormat;
//import java.time.Instant;
//import java.time.ZoneId;
//import java.time.ZoneOffset;
//import java.time.ZonedDateTime;
//import java.time.temporal.ChronoUnit;
//import java.util.Date;
//import java.util.List;
//import java.util.TimeZone;
//
///**
// * XXL-Job FTP文件传输执行器
// * 支持文件上传和下载功能，新增重复文件跳过、失败清理及两种传输模式
// */
//@Component
//public class FtpJob_v2 {
//
//    /**
//     * 增强版FTP文件传输任务
//     * 支持按规则筛选、重复文件跳过、失败清理及传输模式选择
//     */
////    @XxlJob("FtpJob_v1")
//    public void ftpJobHandler() {
//        FtpParam param = paramParser(XxlJobHelper.getJobParam());
//        if (null != param) {
//            try {
//                XxlJobHelper.log("开始执行FTP操作: " + param.getOperation());
//                XxlJobHelper.log("服务器: " + param.getHost() + ":" + param.getPort());
//                XxlJobHelper.log("传输模式: " + param.getTransferMode() + ", 比较模式: " + param.getFileCompareMode());
//                XxlJobHelper.log("本地时区： " + param.getLocalTimezone() + ",远程时区: " + param.getRemoteTimezone());
//                // 创建FTP客户端
//                FTPClient ftpClient = createFtpClient(param);
//                if (ftpClient == null) {
//                    XxlJobHelper.log("无法连接到FTP服务器");
//                    return;
//                }
//
//                // 判断操作
//                boolean success = false;
//                if (Constants.FtpOperation.UPLOAD.equalsIgnoreCase(param.getOperation())) {
//                    success = putFilesByRule(ftpClient, param);
//                } else if (Constants.FtpOperation.DOWNLOAD.equalsIgnoreCase(param.getOperation())) {
//                    success = getFilesByRule(ftpClient, param);
//                } else {
//                    XxlJobHelper.log("不支持的操作类型: " + param.getOperation());
//                }
//
//                // 处理结果
//                if (success) {
//                    XxlJobHelper.log("FTP " + param.getOperation() + " 操作成功");
//                } else {
//                    XxlJobHelper.log("FTP " + param.getOperation() + " 操作失败");
//                }
//                closeFtpClient(ftpClient);
//
//            } catch (Exception e) {
//                XxlJobHelper.log("FTP操作异常: " + e.getMessage());
//            }
//        }
//    }
//
//    // ------------------------------ 传输方式 ------------------------------
//
//    /**
//     * 按规则批量下载文件（新增重复校验和传输模式支持）
//     */
//    private boolean getFilesByRule(FTPClient ftpClient, FtpParam param) {
//        try {
//            String remotePath = param.getRemotePath();
//            String localPath = param.getLocalPath();
//            FTPFile[] allFiles = ftpClient.listFiles(remotePath);
//            if (allFiles == null || allFiles.length == 0) {
//                XxlJobHelper.log("远程目录不存在或为空: " + remotePath);
//                return false;
//            }
//
//            List<FTPFile> matchedFiles = FileFilterUtil.ftpFileFilter(allFiles, param);
//            if (matchedFiles.isEmpty()) {
//                XxlJobHelper.log("未找到符合条件的文件");
//                return true;
//            }
//
//            XxlJobHelper.log("找到 " + matchedFiles.size() + " 个符合条件的文件，开始处理...");
//
//            int successCount = 0;
//            for (FTPFile remoteFile : matchedFiles) {
//                String fileName = remoteFile.getName();
//                String remoteFilePath = buildRemoteFilePath(remotePath, fileName);
//                String localFilePath = buildLocalFilePath(localPath, fileName);
//                File localFile = new File(localFilePath);
//
//                // 检查文件是否已存在且一致，一致则跳过
//                if (localFile.exists() && isFileConsistent(localFile, remoteFile, param)) {
//                    XxlJobHelper.log("文件已存在且一致，跳过下载: " + fileName);
//                    continue;
//                }
//
//                // 执行下载
//                if (getFile(ftpClient, param, localFilePath, remoteFilePath)) {
//                    successCount++;
//                } else {
//                    // 下载失败，清理本地文件
//                    cleanupFailedFile(localFile, "下载");
//                }
//            }
//
//            XxlJobHelper.log("下载完成，成功: " + successCount + " 个，失败: " + (matchedFiles.size() - successCount) + " 个");
//            return successCount > 0;
//
//        } catch (Exception e) {
//            XxlJobHelper.log("批量下载文件异常: " + e.getMessage());
//            return false;
//        }
//    }
//
//    /**
//     * 按规则批量上传文件（新增重复校验和传输模式支持）
//     */
//    private boolean putFilesByRule(FTPClient ftpClient, FtpParam param) {
//        try {
//            String remotePath = param.getRemotePath();
//            String localPath = param.getLocalPath();
//            File localDir = new File(localPath);
//            File[] allFiles = localDir.listFiles();
//            if (allFiles == null || allFiles.length == 0) {
//                XxlJobHelper.log("本地目录不存在或为空: " + localPath);
//                return false;
//            }
//
//            List<File> matchedFiles = FileFilterUtil.fileFilter(allFiles, param);
//            if (matchedFiles.isEmpty()) {
//                XxlJobHelper.log("未找到符合条件的文件");
//                return true;
//            }
//
//            XxlJobHelper.log("找到 " + matchedFiles.size() + " 个符合条件的文件，开始处理...");
//
//            int successCount = 0;
//            for (File localFile : matchedFiles) {
//                String fileName = localFile.getName();
//                String remoteFilePath = buildRemoteFilePath(remotePath, fileName);
//                String localFilePath = buildLocalFilePath(localPath, fileName);
//
//                // 检查远程文件是否已存在且一致，一致则跳过
//                FTPFile remoteFile = getRemoteFileByName(ftpClient, remotePath, fileName);
//                if (remoteFile != null && isFileConsistent(localFile, remoteFile, param)) {
//                    XxlJobHelper.log("文件已存在且一致，跳过上传: " + fileName);
//                    continue;
//                }
//
//                // 执行上传
//                if (putFile(ftpClient, param, localFilePath, remoteFilePath)) {
//                    successCount++;
//                } else {
//                    // 上传失败，清理远程文件
//                    cleanupFailedRemoteFile(ftpClient, remoteFilePath, "上传");
//                }
//            }
//
//            XxlJobHelper.log("上传完成，成功: " + successCount + " 个，失败: " + (matchedFiles.size() - successCount) + " 个");
//            return successCount > 0;
//
//        } catch (Exception e) {
//            XxlJobHelper.log("批量上传文件异常: " + e.getMessage());
//            return false;
//        }
//    }
//
//    /**
//     * 下载单个文件（支持删除重建/断点续传）
//     */
//    private boolean getFile(FTPClient ftpClient, FtpParam param, String localFilePath, String remoteFilePath) {
//        try {
//            File localFile = new File(localFilePath);
//            createLocalDir(localFile); // 确保本地目录存在
//
//            long remoteFileSize = getRemoteFileSize(ftpClient, remoteFilePath);
//            if (remoteFileSize < 0) {
//                XxlJobHelper.log("无法获取远程文件大小: " + remoteFilePath);
//                return false;
//            }
//
//            // 断点续传模式
//            if (Constants.TransferMode.RESUME.equals(param.getTransferMode()) && localFile.exists() && localFile.length() > 0
//                    && localFile.length() < remoteFileSize && ftpClient.hasFeature("REST")) {
//
//                return resumeDownload(ftpClient, param, remoteFilePath, localFile, remoteFileSize);
//            }
//
//            // 删除重建模式（默认）
//            return deleteAndRecreateDownload(ftpClient, param, remoteFilePath, localFile, remoteFileSize);
//
//        } catch (Exception e) {
//            XxlJobHelper.log("下载文件异常 " + remoteFilePath + ": " + e.getMessage());
//            return false;
//        }
//    }
//
//    /**
//     * 上传单个文件（支持删除重建/断点续传）
//     */
//    private boolean putFile(FTPClient ftpClient, FtpParam param, String localFilePath, String remoteFilePath) {
//        String fileName = null;
//        String remotePath = param.getRemotePath();
//        try {
//            File localFile = new File(localFilePath);
//            if (!localFile.exists() || !localFile.isFile()) {
//                XxlJobHelper.log("本地文件不存在或不是文件: " + localFilePath);
//                return false;
//            }
//            fileName = localFile.getName();
//
//            // 创建远程目录
//            if (!ftpClient.changeWorkingDirectory(remotePath) && !createRemoteDirectory(ftpClient, remotePath)) {
//                XxlJobHelper.log("无法创建远程目录: " + remotePath);
//                return false;
//            }
//
//            long localFileSize = localFile.length();
//            FTPFile remoteFile = getRemoteFileByName(ftpClient, remotePath, fileName);
//            long remoteFileSize = (remoteFile != null) ? remoteFile.getSize() : 0;
//
//            // 断点续传模式
//            if (Constants.TransferMode.RESUME.equals(param.getTransferMode()) && remoteFile != null && remoteFileSize > 0
//                    && remoteFileSize < localFileSize && ftpClient.hasFeature("REST")) {
//
//                return resumeUpload(ftpClient, param, localFile, remoteFilePath, remoteFileSize);
//            }
//
//            // 删除重建模式（默认）
//            return deleteAndRecreateUpload(ftpClient, param, localFile, remoteFilePath, localFileSize);
//
//        } catch (Exception e) {
//            XxlJobHelper.log("上传文件异常 " + fileName + ": " + e.getMessage());
//            return false;
//        }
//    }
//
//    // ------------------------------ 重传模式 ------------------------------
//
//    /**
//     * 断点续传下载
//     */
//    private boolean resumeDownload(FTPClient ftpClient, FtpParam param, String remoteFilePath, File localFile, long remoteFileSize) throws IOException {
//        long localSize = localFile.length();
//        XxlJobHelper.log("断点续传下载: " + remoteFilePath + "（从 " + localSize + " 字节开始）");
//
//        try {
//            // 设置断点续传偏移量（此方法返回void）
//            ftpClient.setRestartOffset(localSize);
//            // 检查FTP服务器响应码，200表示成功
//            int reply = ftpClient.getReplyCode();
//            if (!(reply >= 200 && reply < 300)) {
//                XxlJobHelper.log("设置断点续传偏移量失败，响应码: " + reply + "，降级为删除重建模式");
//                return deleteAndRecreateDownload(ftpClient, param, remoteFilePath, localFile, remoteFileSize);
//            }
//        } catch (IOException e) {
//            XxlJobHelper.log("设置断点续传偏移量发生异常: " + e.getMessage() + "，降级为删除重建模式");
//            return deleteAndRecreateDownload(ftpClient, param, remoteFilePath, localFile, remoteFileSize);
//        }
//
//        try (RandomAccessFile raf = new RandomAccessFile(localFile, "rw")) {
//            raf.seek(localSize); // 定位到断点位置
//            boolean success = ftpClient.retrieveFile(remoteFilePath, new FileOutputStream(raf.getFD()));
//
//            if (success && localFile.length() == remoteFileSize) {
//                XxlJobHelper.log("断点续传下载成功: " + remoteFilePath + " -> " + localFile.getAbsolutePath());
//
//                changeLocalFileTime(ftpClient, param, localFile, remoteFilePath);
//
//                return true;
//            } else {
//                XxlJobHelper.log("断点续传下载不完整，实际大小: " + localFile.length() + "，预期: " + remoteFileSize);
//                cleanupFailedFile(localFile, "断点续传下载");
//                return false;
//            }
//        }
//    }
//
//    /**
//     * 删除重建下载
//     */
//    private boolean deleteAndRecreateDownload(FTPClient ftpClient, FtpParam param, String remoteFilePath, File localFile, long remoteFileSize) throws IOException {
//        // 删除已存在的不完整文件
//        if (localFile.exists() && !localFile.delete()) {
//            XxlJobHelper.log("无法删除已存在文件: " + localFile.getAbsolutePath());
//            return false;
//        }
//
//        // 完整下载
//        try (OutputStream outputStream = new FileOutputStream(localFile)) {
//            boolean success = ftpClient.retrieveFile(remoteFilePath, outputStream);
//            if (success && localFile.length() == remoteFileSize) {
//                XxlJobHelper.log("完整下载成功: " + remoteFilePath + " -> " + localFile.getAbsolutePath());
//
//                changeLocalFileTime(ftpClient, param, localFile, remoteFilePath);
//
//                return true;
//            } else {
//                XxlJobHelper.log("完整下载失败，服务器响应: " + ftpClient.getReplyString());
//                cleanupFailedFile(localFile, "完整下载");
//                return false;
//            }
//        }
//    }
//
//    /**
//     * 断点续传上传
//     */
//    private boolean resumeUpload(FTPClient ftpClient, FtpParam param, File localFile, String remoteFilePath, long remoteFileSize) throws IOException {
//        XxlJobHelper.log("断点续传上传: " + localFile.getName() + "（从 " + remoteFileSize + " 字节开始）");
//
//        try {
//            // 设置断点续传偏移量（此方法返回void）
//            ftpClient.setRestartOffset(remoteFileSize);
//
//            // 检查FTP服务器响应码，200-299表示成功
//            int reply = ftpClient.getReplyCode();
//            if (!(reply >= 200 && reply < 300)) {
//                XxlJobHelper.log("设置断点续传偏移量失败，响应码: " + reply + "，降级为删除重建模式");
//                return deleteAndRecreateUpload(ftpClient, param, localFile, remoteFilePath, localFile.length());
//            }
//        } catch (IOException e) {
//            XxlJobHelper.log("设置断点续传偏移量发生异常: " + e.getMessage() + "，降级为删除重建模式");
//            return deleteAndRecreateUpload(ftpClient, param, localFile, remoteFilePath, localFile.length());
//        }
//
//        try (RandomAccessFile raf = new RandomAccessFile(localFile, "r")) {
//            raf.seek(remoteFileSize); // 定位到断点位置
//            boolean success = ftpClient.storeFile(remoteFilePath, new FileInputStream(raf.getFD()));
//
//            FTPFile newRemoteFile = getRemoteFileByName(ftpClient, param.getRemotePath(), localFile.getName());
//            if (success && newRemoteFile != null && newRemoteFile.getSize() == localFile.length()) {
//                XxlJobHelper.log("断点续传上传成功: " + localFile.getName() + " -> " + param.getRemotePath());
//
//                changeRemoteFileTime(ftpClient, param, localFile);
//
//                return true;
//            } else {
//                XxlJobHelper.log("断点续传上传不完整，实际大小: " + (newRemoteFile != null ? newRemoteFile.getSize() : 0));
//                cleanupFailedRemoteFile(ftpClient, remoteFilePath, "断点续传上传");
//                return false;
//            }
//        }
//    }
//
//
//    /**
//     * 删除重建上传
//     */
//    private boolean deleteAndRecreateUpload(FTPClient ftpClient, FtpParam param, File localFile, String remoteFilePath, long localFileSize) throws IOException {
//        String fileName = localFile.getName();
//        // 删除已存在的远程文件
//        FTPFile existingRemoteFile = getRemoteFileByName(ftpClient, param.getRemotePath(), fileName);
//        if (existingRemoteFile != null && !ftpClient.deleteFile(remoteFilePath)) {
//            XxlJobHelper.log("无法删除远程文件: " + remoteFilePath);
//            return false;
//        }
//
//        // 完整上传
//        try (InputStream inputStream = new FileInputStream(localFile)) {
//            boolean success = ftpClient.storeFile(remoteFilePath, inputStream);
//            FTPFile newRemoteFile = getRemoteFileByName(ftpClient, param.getRemotePath(), fileName);
//
//            if (success && newRemoteFile != null && newRemoteFile.getSize() == localFileSize) {
//                XxlJobHelper.log("完整上传成功: " + fileName + " -> " + param.getRemotePath());
//
//                changeRemoteFileTime(ftpClient, param, localFile);
//
//                return true;
//            } else {
//                XxlJobHelper.log("完整上传失败，服务器响应: " + ftpClient.getReplyString());
//                cleanupFailedRemoteFile(ftpClient, remoteFilePath, "完整上传");
//                return false;
//            }
//        }
//    }
//
//    // ------------------------------ 工具方法 ------------------------------
//
//    /**
//     * 检查文件是否一致（支持大小+时间/MD5模式）
//     */
//    private boolean isFileConsistent(File localFile, FTPFile remoteFile, FtpParam param) {
//        // 空值与存在性校验
//        if (localFile == null || !localFile.exists() || remoteFile == null) {
//            XxlJobHelper.log("文件为空，无法进行一致性检查");
//            return false;
//        }
//
//        // 大小不一致返回false
//        if (localFile.length() != remoteFile.getSize()) {
//            XxlJobHelper.log(String.format("文件大小不一致 - 本地大小: %d, 远程大小: %d",
//                    localFile.length(), remoteFile.getSize()));
//            return false;
//        }
//
//        // 大小+时间不一致返回false（默认）
//        if (Constants.CompareMode.SIZE_TIME.equals(param.getFileCompareMode())) {
//
//            long localTime = localFile.lastModified();
//            Instant localInstant = Instant.ofEpochMilli(localTime);
//            ZoneId localZoneId = ZoneId.of(param.getLocalTimezone());
//            ZonedDateTime localZoneTime = ZonedDateTime.ofInstant(localInstant, localZoneId);
//            ZonedDateTime localUtcTime = localZoneTime.withZoneSameInstant(ZoneOffset.UTC); // 转换为UTC
//
//            long remoteTime = remoteFile.getTimestamp().getTimeInMillis();
//            Instant remoteInstant = Instant.ofEpochMilli(remoteTime);
//            ZoneId remoteZoneId = ZoneId.of(param.getRemoteTimezone());
//            ZonedDateTime remoteZoneTime = ZonedDateTime.ofInstant(remoteInstant, remoteZoneId);
//            ZonedDateTime remoteUtcTime = remoteZoneTime.withZoneSameInstant(ZoneOffset.UTC); // 转换为UTC
//
//            System.out.println(remoteFile.getTimestampInstant());
//
//            System.out.println(localZoneId);
//            System.out.println(remoteZoneId);
//            System.out.println("localZoneTime" + localZoneTime);
//            System.out.println("remoteZoneTime" + remoteZoneTime);
//            System.out.println("localUtcTime" + localUtcTime);
//            System.out.println("remoteUtcTime" + remoteUtcTime);
//
//            // 3. 允许1秒内的时间差（解决时区/秒级差异问题）
//            boolean timeConsistent = Math.abs(ChronoUnit.MILLIS.between(localZoneTime, remoteZoneTime)) < 1000;
//
//            if (!timeConsistent) {
//                XxlJobHelper.log(String.format(
//                        "文件时间不一致 - 本地时间: %d(%s), 远程时间: %d(%s), 差值: %dH (%dms) ",
//                        localTime, localZoneTime, remoteTime, remoteZoneTime,
//                        Math.abs(ChronoUnit.HOURS.between(localZoneTime, remoteZoneTime)),
//                        Math.abs(ChronoUnit.MILLIS.between(localZoneTime, remoteZoneTime))
//                ));
//            }
//            return timeConsistent;
//        }
//
//        // MD5模式（需额外实现MD5计算逻辑）
//        if (Constants.CompareMode.MD5.equals(param.getFileCompareMode())) {
//            // 实际项目中需实现本地文件MD5计算和远程文件MD5获取
//            XxlJobHelper.log("MD5比较模式暂未实现，默认使用大小比较");
//            return true;
//        }
//
//        return false;
//    }
//
//    /**
//     * 清理失败的本地文件
//     */
//    private void cleanupFailedFile(File file, String operation) {
//        if (file.exists() && file.delete()) {
//            XxlJobHelper.log(operation + "失败，已清理本地文件: " + file.getAbsolutePath());
//        } else if (file.exists()) {
//            XxlJobHelper.log(operation + "失败，清理本地文件失败: " + file.getAbsolutePath());
//        }
//    }
//
//    /**
//     * 清理失败的远程文件
//     */
//    private void cleanupFailedRemoteFile(FTPClient ftpClient, String remoteFilePath, String operation) {
//        try {
//            if (ftpClient.deleteFile(remoteFilePath)) {
//                XxlJobHelper.log(operation + "失败，已清理远程文件: " + remoteFilePath);
//            } else {
//                XxlJobHelper.log(operation + "失败，清理远程文件失败: " + remoteFilePath);
//            }
//        } catch (IOException e) {
//            XxlJobHelper.log(operation + "失败，清理远程文件异常: " + e.getMessage());
//        }
//    }
//
//    /**
//     * 获取远程文件大小
//     */
//    private long getRemoteFileSize(FTPClient ftpClient, String remoteFilePath) throws IOException {
//        FTPFile[] files = ftpClient.listFiles(remoteFilePath);
//        return (files != null && files.length > 0 && files[0].isFile()) ? files[0].getSize() : -1;
//    }
//
//    /**
//     * 根据文件名查询远程文件
//     */
//    private FTPFile getRemoteFileByName(FTPClient ftpClient, String remoteDir, String fileName) throws IOException {
//        FTPFile[] files = ftpClient.listFiles(remoteDir);
//        if (files != null) {
//            for (FTPFile file : files) {
//                if (file.getName().equals(fileName) && file.isFile()) {
//                    return file;
//                }
//            }
//        }
//        return null;
//    }
//
//    /**
//     * 构建本地文件路径
//     */
//    private String buildLocalFilePath(String localDir, String fileName) {
//        return localDir + File.separator + fileName;
//    }
//
//    /**
//     * 构建远程文件路径
//     */
//    private String buildRemoteFilePath(String remoteDir, String fileName) {
//        return remoteDir + ("/".equals(remoteDir) ? "" : "/") + fileName;
//    }
//
//    /**
//     * 修改远程文件时间
//     */
//    private void changeRemoteFileTime(FTPClient ftpClient, FtpParam param, File localFile) {
//        String remoteFilePath = buildRemoteFilePath(param.getRemotePath(), localFile.getName());
//        // 1. 准备时间参数 - 使用UTC时区确保与FTP服务器兼容
//        Date localFileDate = new Date(localFile.lastModified());
//        SimpleDateFormat utcFormat = new SimpleDateFormat("yyyyMMddHHmmss");
//        utcFormat.setTimeZone(TimeZone.getTimeZone(param.getRemoteTimezone()));
//        String timeString = utcFormat.format(localFileDate);
//        long unixTimestamp = localFile.lastModified() / 1000;
//
//        // 2. 定义命令列表，按优先级尝试
//        String[] commands = {
//                String.format("MFMT %s %s", timeString, param.getRemotePath()),  // 优先尝试字符串格式
//                String.format("MFMT %d %s", unixTimestamp, remoteFilePath) // 备选尝试时间戳格式
//        };
//
//        // 3. 尝试执行命令
//        for (String command : commands) {
//            try {
//                int replyCode = ftpClient.sendCommand(command);
//                String replyString = ftpClient.getReplyString(); // 获取完整响应信息
//
//                if (replyCode >= 200 && replyCode < 300) {
//                    XxlJobHelper.log(String.format(
//                            "成功设置远程文件修改时间: %s (使用命令: %s, 响应: %s)",
//                            remoteFilePath, command, replyString.trim()
//                    ));
//                    return; // 成功则退出
//                } else {
//                    XxlJobHelper.log(String.format(
//                            "设置时间失败，命令: %s, 响应码: %d, 响应信息: %s",
//                            command, replyCode, replyString.trim()
//                    ));
//                }
//            } catch (IOException e) {
//                XxlJobHelper.log(String.format(
//                        "执行命令时发生异常: %s, 命令: %s, 异常信息: %s",
//                        remoteFilePath, command, e.getMessage()
//                ));
//                // 对于IO异常，不再尝试其他命令格式
//                return;
//            }
//        }
//
//        // 4. 所有尝试均失败
//        XxlJobHelper.log("所有MFMT命令格式均不被支持，无法设置远程文件时间: " + remoteFilePath);
//    }
//
//    private void changeLocalFileTime(FTPClient ftpClient, FtpParam param, File localFile, String remoteFilePath) {
//        // 使用UTC时区解析，与FTP服务器时间保持一致
//        SimpleDateFormat format;
//        try {
//            // 1. 获取远程文件时间字符串（可能包含状态码前缀，如"213 20250813153000"）
//            String remoteTimeStr = ftpClient.getModificationTime(remoteFilePath);
//            if (remoteTimeStr == null || remoteTimeStr.trim().isEmpty()) {
//                XxlJobHelper.log("获取远程文件时间失败，远程路径: " + remoteFilePath);
//                return;
//            }
//            // 2. 提取纯时间部分（过滤非数字字符）
//            switch (remoteTimeStr.length()) {
//                case 14 -> {
//                    format = new SimpleDateFormat("yyyyMMddHHmmss");
//                    format.setTimeZone(TimeZone.getTimeZone(param.getRemoteTimezone()));
//                }
//                case 18 -> {
//                    format = new SimpleDateFormat("yyyyMMddHHmmss.SSS");
//                    format.setTimeZone(TimeZone.getTimeZone(param.getRemoteTimezone()));
//                }
//                default -> {
//                    XxlJobHelper.log("远程时间格式无效，原始值: " + remoteTimeStr + "，远程路径: " + remoteFilePath);
//                    return;
//                }
//            }
//            // 3. 解析时间并转换为毫秒时间戳
//            Date remoteDate = format.parse(remoteTimeStr);
//            long targetTime = remoteDate.getTime();
//
//            // 4. 设置本地文件最后修改时间，并处理返回结果
//            boolean setSuccess = localFile.setLastModified(targetTime);
//            if (setSuccess) {
//                XxlJobHelper.log(String.format(
//                        "本地文件时间同步成功: %s -> %s (时间: %s)",
//                        remoteFilePath,
//                        localFile.getAbsolutePath(),
//                        format.format(remoteDate)
//                ));
//            } else {
//                XxlJobHelper.log(String.format(
//                        "本地文件时间同步失败: 无法修改文件时间，路径: %s",
//                        localFile.getAbsolutePath()
//                ));
//            }
//
//        } catch (ParseException e) {
//            XxlJobHelper.log(String.format(
//                    "时间解析失败: 格式不匹配，远程路径: %s，异常: %s",
//                    remoteFilePath,
//                    e.getMessage()
//            ));
//        } catch (IOException e) {
//            XxlJobHelper.log(String.format(
//                    "获取远程文件时间异常: 远程路径: %s，异常: %s",
//                    remoteFilePath,
//                    e.getMessage()
//            ));
//        } catch (Exception e) {
//            XxlJobHelper.log(String.format(
//                    "同步本地文件时间发生未知异常: 远程路径: %s，异常: %s",
//                    remoteFilePath,
//                    e.getMessage()
//            ));
//        }
//    }
//
//    /**
//     * 创建本地目录
//     */
//    private void createLocalDir(File file) {
//        if (file == null) {
//            XxlJobHelper.log("创建本地目录失败：文件对象为null");
//            return;
//        }
//
//        File parentDir = file.getParentFile();
//        if (parentDir == null) {
//            XxlJobHelper.log("无需创建目录：文件没有父目录");
//            return;
//        }
//
//        if (parentDir.exists()) {
//            XxlJobHelper.log("目录已存在，无需创建：" + parentDir.getAbsolutePath());
//            return;
//        }
//
//        // 尝试创建目录
//        boolean isCreated = parentDir.mkdirs();
//        if (isCreated) {
//            XxlJobHelper.log("目录创建成功：" + parentDir.getAbsolutePath());
//        } else {
//            XxlJobHelper.log("警告：目录创建失败，可能导致后续操作异常：" + parentDir.getAbsolutePath());
//        }
//    }
//
//    /**
//     * 创建远程目录
//     */
//    private static boolean createRemoteDirectory(FTPClient ftpClient, String remoteDir) throws IOException {
//        String[] dirs = remoteDir.split("/");
//        String currentDir = "";
//        for (String dir : dirs) {
//            if (dir.isEmpty()) continue;
//            currentDir += "/" + dir;
//            if (!ftpClient.changeWorkingDirectory(currentDir) && !ftpClient.makeDirectory(currentDir)) {
//                return false;
//            }
//            ftpClient.changeWorkingDirectory(currentDir);
//        }
//        return true;
//    }
//
//    // ------------------------------ FTP连接管理 ------------------------------
//
//    /**
//     * 创建FTP客户端连接
//     */
//    private static FTPClient createFtpClient(FtpParam param) {
//        FTPClient ftpClient = new FTPClient();
//        try {
//            ftpClient.connect(param.getHost(), param.getPort());
//            int replyCode = ftpClient.getReplyCode();
//            if (!FTPReply.isPositiveCompletion(replyCode)) {
//                XxlJobHelper.log("FTP服务器拒绝连接，响应码: " + replyCode);
//                ftpClient.disconnect();
//                return null;
//            }
//
//            if (!ftpClient.login(param.getUsername(), param.getPassword())) {
//                XxlJobHelper.log("FTP登录失败");
//                ftpClient.disconnect();
//                return null;
//            }
//
//            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//            ftpClient.setControlEncoding(StandardCharsets.UTF_8.name());
//            ftpClient.enterLocalPassiveMode(); // 被动模式
//            return ftpClient;
//
//        } catch (Exception e) {
//            XxlJobHelper.log("创建FTP连接失败: " + e.getMessage());
//            closeFtpClient(ftpClient);
//            return null;
//        }
//    }
//
//    /**
//     * 关闭FTP连接
//     */
//    private static void closeFtpClient(FTPClient ftpClient) {
//        try {
//            if (ftpClient != null && ftpClient.isConnected()) {
//                ftpClient.logout();
//                ftpClient.disconnect();
//            }
//        } catch (IOException e) {
//            XxlJobHelper.log("关闭FTP连接时出错: " + e.getMessage());
//        }
//    }
//
//
//    private static FtpParam paramParser(String paramJson) {
//        // 解析参数
//        if (paramJson == null || paramJson.trim().isEmpty()) {
//            XxlJobHelper.log("参数不能为空，请提供正确的JSON格式参数");
//            return null;
//        }
//        paramJson = paramJson.replace("\\", "\\\\");
//        FtpParam param = GsonTool.fromJson(paramJson, FtpParam.class);
//
//        if (StringUtils.isBlank(param.getHost()) || param.getPort() <= 0) {
//            XxlJobHelper.log("FTP服务器地址和端口不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getUsername()) || StringUtils.isBlank(param.getPassword())) {
//            XxlJobHelper.log("用户名或密码不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getOperation())) {
//            XxlJobHelper.log("FTP操作不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getLocalPath()) || StringUtils.isBlank(param.getRemotePath())) {
//            XxlJobHelper.log("本地目录或远程目录不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getFileNamePattern())) {
//            XxlJobHelper.log("文件名模式不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getLocalTimezone()) || StringUtils.isBlank(param.getRemoteTimezone())) {
//            XxlJobHelper.log("本地时区或远程时区不能为空");
//            return null;
//        } else {
//            if (!param.getLocalTimezone().matches("^(UTC|GMT)[+-]\\d+$")) {
//                XxlJobHelper.log("时区格式无效: " + param.getLocalTimezone() + ", 应符合UTC±N或GMT±N格式");
//                return null;
//            }
//        }
//        if (StringUtils.isBlank(param.getFileCompareMode())) {
//            XxlJobHelper.log("文件比较方式不能为空");
//            return null;
//        }
//        if (StringUtils.isBlank(param.getTransferMode())) {
//            XxlJobHelper.log("传输方式不能为空");
//            return null;
//        }
//        return param;
//    }
//}